package com.yutian.selfservice.search.service.impl;

import com.yutian.selfservice.search.mapper.KeySearchMapper;
import com.yutian.selfservice.search.service.KeySearchService;
import com.yutian.selfservice.support.utils.Result;
import lombok.Builder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class KeySearchServiceImpl implements KeySearchService {
    @Autowired
    private KeySearchMapper keySearchMapper;


    private final Queue<KeyRequest> queue = new LinkedBlockingDeque<>();
    private final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2, r -> new Thread(r,"KeySearchScheduled"));

    @PostConstruct
    public void execute() {
        executorService.scheduleAtFixedRate(() -> execute0(), 0, 10, TimeUnit.MILLISECONDS);
    }

    @PreDestroy
    public void destory() {
        executorService.shutdown();
    }

    @Override
    public Result search(String key) {
        CompletableFuture<Result> completableFuture = new CompletableFuture();
        queue.add(KeyRequest.builder().key(key).future(completableFuture).build());
        try {
            return completableFuture.get(500, TimeUnit.MILLISECONDS);
        } catch (TimeoutException | InterruptedException | ExecutionException e) {
            return Result.fail("服务器繁忙");
        }
    }


    private void execute0() {
        try {
            List<KeyRequest> requests = new ArrayList<>();
            int size = queue.size();
            if (size == 0) {
                return;
            }
            for (int i = 0; i < size; i++) {
                requests.add(queue.poll());
            }
            Map<String, Result> responses = doExecute(requests);
            requests.forEach(x -> x.getFuture().complete(responses.getOrDefault(x.key, Result.fail(""))));
        } catch (Exception e) {
            log.error("批量查询处理结束");
        }
    }

    /**
     * 根据key 进行批量查询
     *
     * @param requests
     * @return
     */
    private Map<String, Result> doExecute(List<KeyRequest> requests) {
        String keys = requests.stream().distinct().map(x -> x.getKey()).collect(Collectors.joining("|"));
        List<String> list = keySearchMapper.selectKeys(keys);
        Map<String, Result> resultMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(list)) {
            requests.forEach(x -> {
                List<String> keyTitle = list.stream().filter(y -> y.contains(x.getKey())).collect(Collectors.toList());
                resultMap.put(x.getKey(), Result.success(keyTitle));
            });
        }
        return resultMap;
    }

    @Data
    @Builder
    public static class KeyRequest {
        private String key;
        private CompletableFuture<Result> future;

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            KeyRequest that = (KeyRequest) o;
            return Objects.equals(key, that.key);
        }

        @Override
        public int hashCode() {
            return Objects.hash(key);
        }
    }

}
